function [ hardSymbols, softSymbols, MSE_Real, MSE] = kalmanEqualizer( Current_Frame_toEqualize,Current_Tranining_toEqualize,Data_After, Original_Current_Frame, ...
                                             Nf, Nb, Oversample, Data_Before,reset, w )
%KALMANEQUALIZER Summary of this function goes here
%   Detailed explanation goes here

       
% useDataToAdapt=0;   % 0 = adaptation only during training sequence 
                    % 1 = adatation with detected data

global LUT_Current                   

useDataToAdapt=1;
dataConstellations = LUT_Current;
p = 1;

midTapIndex=round(Nf/1);
N=Nf+ Nb;

numDataSymbols=256;
numTrainingSymbols=31;

rxSymbols = [Current_Tranining_toEqualize Current_Frame_toEqualize Data_After(1:midTapIndex*Oversample)];                    
% rxSymbols = [Data_Before(end+(midTapIndex-Nf)*Oversample+1:end) Current_Tranining_toEqualize Current_Frame_toEqualize Data_After(1:midTapIndex*Oversample)];                    

rxSymbols = downsample(rxSymbols,Oversample/p);

trainingSymbols = Original_Current_Frame(1:Oversample:numTrainingSymbols*Oversample);
Perfect_Data_Symbols = Original_Current_Frame((numTrainingSymbols)*Oversample+1:Oversample:(numTrainingSymbols+256+20)*Oversample);

numSymbolsToEqualize=numDataSymbols+numTrainingSymbols+round(Nf/p);

C=zeros(N,1);
C(midTapIndex)=1;
xN=zeros(N,1);
% reset=1;
hardSymbols=zeros(1,numSymbolsToEqualize);
softSymbols=zeros(1,numSymbolsToEqualize);
errorPlot=zeros(1,numSymbolsToEqualize);
referenceSymbol=0;
trainingCounter=0;
dataCounter=0;
       
%for symbolCounter=1:numSymbolsToEqualize-1
for symbolCounter=1:floor(length(rxSymbols)/p)

   % update xN, the tapped-referenceSymbolDelay line values
   % insert p new samples, p=1 or 2
   new_p_Symbols=transpose(rxSymbols(symbolCounter*p-p+1:symbolCounter*p));
   xN=[new_p_Symbols ; xN(1:Nf-p) ; referenceSymbol; xN(Nf+1:N-1)];
   filterOut= sum(xN .* C);



   if symbolCounter<round(Nf/p)
        referenceSymbol=0;
        C=zeros(N,1);
        C(midTapIndex)=1;
   elseif symbolCounter<numTrainingSymbols+round(Nf/p)
%        w=0.95;
       trainingCounter=trainingCounter+1;
       referenceSymbol=round(trainingSymbols(trainingCounter));
   else
%        w=0.95;
       % Decide which "complex "constellation point was transmitted
       [minValue index]=min( (abs(dataConstellations-filterOut)).^2 );
       rXsymbol=dataConstellations(index) ;
       dataCounter=dataCounter+1;
       referenceSymbol=rXsymbol;
       referenceSymbol = Perfect_Data_Symbols(dataCounter);
       hardSymbols(dataCounter)=rXsymbol;
       softSymbols(dataCounter)=filterOut;
   end

 % Find the error and the detected symbol to be fed-back
 errorValue=referenceSymbol-filterOut;

   % Update filter coefficients
   if ((symbolCounter<numTrainingSymbols+round(Nf/p)) || (useDataToAdapt==1)) && symbolCounter>=round(Nf/p)
   %if symbolCounter >= Nf/p 
       
       PN = kalmanCoefUpdate(xN, N, reset, w );
       C= C + PN*conj(xN)*errorValue ;
       reset=0;
   %end
   end

   errorPlot(symbolCounter)=abs(errorValue)^2;

end

real_error = abs((hardSymbols(1:256)-Perfect_Data_Symbols(1:256))).^2;
MSE_Real = mean(real_error);
MSE = mean(errorPlot(round(Nf/p)+31:end));

softSymbols = softSymbols(1:256);

% softSymbols = downsample(Current_Frame_toEqualize,Oversample);
 end

